/**
 * 测试设置文件
 * 在每个测试文件执行前运行
 */

// 模拟Web Audio API
class MockAudioContext {
  constructor() {
    this.state = 'suspended';
    this.destination = {};
    this.sampleRate = 44100;
  }
  
  createGain() {
    return {
      gain: { value: 1.0 },
      connect: jest.fn(),
      disconnect: jest.fn()
    };
  }
  
  createAnalyser() {
    return {
      fftSize: 2048,
      frequencyBinCount: 1024,
      smoothingTimeConstant: 0.8,
      connect: jest.fn(),
      disconnect: jest.fn(),
      getByteFrequencyData: jest.fn((array) => {
        // 填充模拟数据
        for (let i = 0; i < array.length; i++) {
          array[i] = Math.floor(Math.random() * 255);
        }
      })
    };
  }
  
  createMediaStreamSource(stream) {
    return {
      connect: jest.fn(),
      disconnect: jest.fn()
    };
  }
  
  createScriptProcessor(bufferSize, inputChannels, outputChannels) {
    return {
      connect: jest.fn(),
      disconnect: jest.fn(),
      onaudioprocess: null,
      bufferSize,
      inputChannels,
      outputChannels
    };
  }
  
  createBuffer(channels, length, sampleRate) {
    return {
      getChannelData: () => new Float32Array(length)
    };
  }
  
  createBufferSource() {
    return {
      buffer: null,
      connect: jest.fn(),
      disconnect: jest.fn(),
      start: jest.fn(),
      stop: jest.fn(),
      onended: null
    };
  }
  
  resume() {
    this.state = 'running';
    return Promise.resolve();
  }
  
  suspend() {
    this.state = 'suspended';
    return Promise.resolve();
  }
  
  close() {
    this.state = 'closed';
    return Promise.resolve();
  }
  
  decodeAudioData(buffer) {
    return Promise.resolve({
      duration: 10,
      length: 441000,
      sampleRate: 44100,
      numberOfChannels: 2
    });
  }
}

// 模拟MediaStream API
class MockMediaStream {
  constructor(tracks = []) {
    this.tracks = tracks;
  }
  
  getTracks() {
    return this.tracks;
  }
  
  getAudioTracks() {
    return this.tracks.filter(track => track.kind === 'audio');
  }
  
  getVideoTracks() {
    return this.tracks.filter(track => track.kind === 'video');
  }
  
  addTrack(track) {
    this.tracks.push(track);
  }
  
  removeTrack(track) {
    const index = this.tracks.indexOf(track);
    if (index !== -1) {
      this.tracks.splice(index, 1);
    }
  }
}

class MockMediaStreamTrack {
  constructor(kind = 'audio') {
    this.kind = kind;
    this.enabled = true;
    this.muted = false;
    this.readyState = 'live';
    this.id = Math.random().toString(36).substring(2, 15);
    this.label = `Mock ${kind} track`;
  }
  
  stop() {
    this.readyState = 'ended';
  }
  
  clone() {
    return new MockMediaStreamTrack(this.kind);
  }
}

// 模拟navigator.mediaDevices
const mockMediaDevices = {
  getUserMedia: jest.fn().mockImplementation(constraints => {
    if (constraints && constraints.audio) {
      const audioTrack = new MockMediaStreamTrack('audio');
      return Promise.resolve(new MockMediaStream([audioTrack]));
    }
    return Promise.reject(new Error('Audio constraints required'));
  }),
  
  enumerateDevices: jest.fn().mockResolvedValue([
    {
      deviceId: 'default',
      kind: 'audioinput',
      label: 'Default Microphone',
      groupId: 'default'
    },
    {
      deviceId: 'microphone1',
      kind: 'audioinput',
      label: 'Microphone 1',
      groupId: 'group1'
    },
    {
      deviceId: 'microphone2',
      kind: 'audioinput',
      label: 'Microphone 2',
      groupId: 'group2'
    }
  ])
};

// 模拟AudioProcessingEvent
class MockAudioProcessingEvent {
  constructor() {
    this.inputBuffer = {
      getChannelData: () => {
        const buffer = new Float32Array(4096);
        for (let i = 0; i < buffer.length; i++) {
          buffer[i] = (Math.random() * 2) - 1; // -1.0 到 1.0 之间的随机值
        }
        return buffer;
      },
      sampleRate: 44100,
      length: 4096,
      numberOfChannels: 1
    };
    this.outputBuffer = {
      getChannelData: () => new Float32Array(4096),
      sampleRate: 44100,
      length: 4096,
      numberOfChannels: 1
    };
  }
}

// 模拟performance.now
const originalPerformanceNow = performance.now;
performance.now = jest.fn().mockImplementation(() => Date.now());

// 设置全局模拟
global.AudioContext = MockAudioContext;
global.webkitAudioContext = MockAudioContext;
global.MediaStream = MockMediaStream;
global.MediaStreamTrack = MockMediaStreamTrack;

// 设置navigator模拟
if (!global.navigator) {
  global.navigator = {};
}
global.navigator.mediaDevices = mockMediaDevices;

// 模拟document事件
document.addEventListener = jest.fn((event, callback) => {
  document[`on${event}`] = callback;
});
document.removeEventListener = jest.fn((event, callback) => {
  if (document[`on${event}`] === callback) {
    document[`on${event}`] = null;
  }
});

// 模拟localStorage
const mockLocalStorage = (() => {
  let store = {};
  return {
    getItem: jest.fn(key => store[key] || null),
    setItem: jest.fn((key, value) => {
      store[key] = value.toString();
    }),
    removeItem: jest.fn(key => {
      delete store[key];
    }),
    clear: jest.fn(() => {
      store = {};
    })
  };
})();
Object.defineProperty(global, 'localStorage', { value: mockLocalStorage });

// 模拟console.log和console.error，避免测试输出过多
global.console.log = jest.fn();
global.console.error = jest.fn();
global.console.warn = jest.fn();

// 导出清理函数，让测试文件自己使用
module.exports = {
  clearMocks: () => {
    jest.clearAllMocks();
  },
  restorePerformanceNow: () => {
    performance.now = originalPerformanceNow;
  }
}; 